package com.sinn.gitrepobranchcompare.application;

import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.awt.Desktop;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

public class HtmlServer {

    private static final String RESOURCE_BASE = "/WEB-INF/";

    public static void main(String[] args) throws Exception {
//        // 设置资源根目录
//        String resourceDir = "D:/GitRepoResult"; // 替换为实际路径
//
//        int port = 8000; // HTTP 服务器端口
//
//        // 读取所有符合命名规则的 TXT 文件
//        List<File> txtFiles = findTxtFiles(resourceDir);
//
//        // 为每个 TXT 文件生成 HTML 文件
//        List<String> htmlFileNames = new ArrayList<>();
//        for (File txtFile : txtFiles) {
//            String htmlContent = generateHtml(txtFile);
//            String htmlFileName = txtFile.getName().replace(".txt", ".html");
//            Path htmlFilePath = Paths.get(resourceDir, htmlFileName);
//            Files.write(htmlFilePath, htmlContent.getBytes());
//            htmlFileNames.add(htmlFileName);
//            System.out.println("生成 HTML 文件: " + htmlFilePath);
//        }
//
//        // 生成 index.html 文件
//        generateIndexHtml(resourceDir, htmlFileNames);
//
//        // 启动 HTTP 服务器
//        HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
//        server.createContext("/", new FileHandler(resourceDir));
//        // 注册静态资源处理器
//        server.createContext("/static", new StaticResourceHandler());
//        server.setExecutor(null); // 使用默认的线程池
//        server.start();
//        System.out.println("HTTP 服务器已启动，访问地址: http://localhost:" + port);
//
//        // 打开浏览器
//        if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
//            Desktop.getDesktop().browse(new URI("http://localhost:" + port + "/index.html"));
//        } else {
//            System.err.println("无法打开浏览器，请手动访问: http://localhost:" + port + "/index.html");
//        }
    }

    static class StaticResourceHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String requestPath = exchange.getRequestURI().getPath();
            String resourcePath = "/WEB-INF/" + requestPath.substring("/static".length() + 1);
            InputStream resourceStream = getClass().getResourceAsStream(resourcePath);
            if (resourceStream != null) {
                exchange.sendResponseHeaders(200, 0);
                OutputStream outputStream = exchange.getResponseBody();
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = resourceStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
                resourceStream.close();
                outputStream.close();
            } else {
                String response = "文件未找到: " + requestPath;
                exchange.sendResponseHeaders(404, response.length());
                try (OutputStream os = exchange.getResponseBody()) {
                    os.write(response.getBytes());
                }
            }
        }
    }

    /**
     * 查找资源根目录下所有符合命名规则的 TXT 文件
     *
     * @param resourceDir 资源根目录
     * @return TXT 文件列表
     */
    public List<File> findTxtFiles(String resourceDir) {
        List<File> txtFiles = new ArrayList<>();
        File dir = new File(resourceDir);
        if (dir.isDirectory()) {
            for (File file : dir.listFiles()) {
                if (file.isFile() && file.getName().endsWith(".txt") && file.getName().contains("change_list")) {
                    txtFiles.add(file);
                }
            }
        }
        return txtFiles;
    }

    /**
     * 生成 HTML 文件内容
     *
     * @param txtFile TXT 文件
     * @return HTML 文件内容
     */
    public String generateHtml(File txtFile) {
        StringBuilder html = new StringBuilder();
        html.append("<!DOCTYPE html>\n")
                .append("<html>\n")
                .append("<head>\n")
                .append("    <title>文件内容展示</title>\n")
                .append("    <meta charset=\"utf-8\">\n")
                .append("    <style>\n")
                .append("        body { font-family: Arial, sans-serif; margin: 20px; }\n")
                .append("        table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }\n")
                .append("        table, th, td { border: 1px solid #ccc; }\n")
                .append("        th, td { padding: 10px; text-align: left; }\n")
                .append("        th { background-color: #f4f4f4; }\n")
                .append("        pre { white-space: pre-wrap; }\n")
                .append("       .hidden { display: none; }\n")
                .append("    </style>\n")
                .append("    <link rel=\"stylesheet\" href=\"/static/css/diff2html.min.css\">\n")
                .append("    <script type=\"text/javascript\" src=\"/static/js/diff2html-ui.min.js\"></script>\n")
                .append("</head>\n")
                .append("<body>\n")
                .append("    <h1>文件内容展示</h1>\n")
                .append("    <table>\n")
                .append("        <thead>\n")
                .append("            <tr>\n")
                .append("                <th>App Name</th>\n")
                .append("                <th>Repo Name</th>\n")
                .append("                <th>Compare Type</th>\n")
                .append("                <th>File Change Type</th>\n")
                .append("                <th>File Name</th>\n")
                .append("                <th>SHA-256</th>\n")
                .append("                <th>操作</th>\n")
                .append("            </tr>\n")
                .append("        </thead>\n")
                .append("        <tbody>\n");

        try {
            String content = new String(Files.readAllBytes(txtFile.toPath()));
            int rowIndex = 0;
            for (String line : content.split("\n")) {
                String[] parts = line.split("\t");
                if (parts.length == 6) {
                    String appname = parts[0];
                    String reponame = parts[1];
                    String compareType = parts[2];
                    String fileChangeType = parts[3];
                    String filename = parts[4];
                    String sha256 = parts[5];

                    html.append("            <tr>\n")
                            .append("                <td>").append(appname).append("</td>\n")
                            .append("                <td>").append(reponame).append("</td>\n")
                            .append("                <td>").append(compareType).append("</td>\n")
                            .append("                <td>").append(fileChangeType).append("</td>\n")
                            .append("                <td>").append(filename).append("</td>\n")
                            .append("                <td>").append(sha256).append("</td>\n")
                            .append("                <td><button onclick=\"toggleAndLoadFiles('").append(reponame).append("', '").append(compareType).append("', '").append(sha256.trim().replace("\r", "").replace("\n", "")).append("', ").append(rowIndex).append(")\">展示/隐藏并加载文件</button></td>\n")
                            .append("            </tr>\n");

                    html.append("            <tr id=\"detailsRow").append(rowIndex).append("\" class=\"hidden\">\n")
                            .append("                <td colspan=\"7\">\n")
                            .append("                    <table>\n")
                            .append("                        <tr>\n")
                            .append("                            <td>Log 文件内容</td>\n")
                            .append("                            <td><pre id=\"logContentFirstLine").append(rowIndex).append("\">未加载</pre><button id=\"logShowMoreBtn").append(rowIndex).append("\" onclick=\"toggleLogView(").append(rowIndex).append(")\" class=\"hidden\">展示更多</button><pre id=\"logContentFull").append(rowIndex).append("\" class=\"hidden\"></pre></td>\n")
                            .append("                        </tr>\n")
                            .append("                        <tr>\n")
                            .append("                            <td>Diff 文件内容</td>\n")
                            .append("                            <td><pre id=\"diffContent").append(rowIndex).append("\">未加载</pre></td>\n")
                            .append("                        </tr>\n")
                            .append("                        <tr>\n")
                            .append("                            <td>Detail 文件内容</td>\n")
                            .append("                            <td><div id=\"detailContent").append(rowIndex).append("\">未加载</div></td>\n")
                            .append("                        </tr>\n")
                            .append("                    </table>\n")
                            .append("                </td>\n")
                            .append("            </tr>\n");

                    rowIndex++;
                }
            }
        } catch (IOException e) {
            System.err.println("读取文件失败: " + txtFile.getAbsolutePath());
            e.printStackTrace();
        }

        html.append("        </tbody>\n")
                .append("    </table>\n")
                .append("    <script src=\"/static/js/diff2html-ui.min.js\"></script>\n")
                .append("    <script>\n")
                .append("        function adjustCompareType(compareType) {\n")
                .append("            if (compareType === 'source -> grey') return 'grey';\n")
                .append("            if (compareType === 'source -> target') return 'target';\n")
                .append("            if (compareType === 'grey -> target') return 'greyTarget';\n")
                .append("            throw new Error('未知的 compareType: ' + compareType);\n")
                .append("        }\n")
                .append("        function loadFiles(reponame, compareType, sha256, rowIndex) {\n")
                .append("            const adjustedCompareType = adjustCompareType(compareType);\n")
                .append("            const logFilePath = `./${reponame}/${adjustedCompareType}/log/${sha256}.txt`;\n")
                .append("            const diffFilePath = `./${reponame}/${adjustedCompareType}/diff/${sha256}.txt`;\n")
                .append("            const detailFilePath = `./${reponame}/${adjustedCompareType}/detail/${sha256}.txt`;\n")
                .append("            loadFile(logFilePath, 'logContentFirstLine' + rowIndex, 'logContentFull' + rowIndex, 'logShowMoreBtn' + rowIndex);\n")
                .append("            loadDiffFile(diffFilePath, 'diffContent' + rowIndex);\n")
                .append("            loadDetailFile(detailFilePath, 'detailContent' + rowIndex);\n")
                .append("        }\n")
                .append("        function loadFile(filePath, firstLineId, fullContentId, showMoreBtnId) {\n")
                .append("            fetch(filePath)\n")
                .append("                .then(response => {\n")
                .append("                    if (!response.ok) throw new Error('文件加载失败: ' + response.statusText);\n")
                .append("                    return response.text();\n")
                .append("                })\n")
                .append("                .then(data => {\n")
                .append("                    const lines = data.split('\\n');\n")
                .append("                    const firstLine = lines[0];\n")
                .append("                    document.getElementById(firstLineId).textContent = firstLine;\n")
                .append("                    document.getElementById(fullContentId).textContent = data;\n")
                .append("                    if (lines.length > 1) {\n")
                .append("                        document.getElementById(showMoreBtnId).classList.remove('hidden');\n")
                .append("                    }\n")
                .append("                })\n")
                .append("                .catch(error => {\n")
                .append("                    console.error('读取文件时出错:', error);\n")
                .append("                    document.getElementById(firstLineId).textContent = '无法加载文件: ' + error.message;\n")
                .append("                });\n")
                .append("        }\n")
                .append("        function loadDiffFile(filePath, blockId) {\n")
                .append("            fetch(filePath)\n")
                .append("                .then(response => {\n")
                .append("                    if (!response.ok) throw new Error('文件加载失败: ' + response.statusText);\n")
                .append("                    return response.text();\n")
                .append("                })\n")
                .append("                .then(data => {\n")
                .append("                    document.getElementById(blockId).textContent = data;\n")
                .append("                })\n")
                .append("                .catch(error => {\n")
                .append("                    console.error('读取文件时出错:', error);\n")
                .append("                    document.getElementById(blockId).textContent = '无法加载文件: ' + error.message;\n")
                .append("                });\n")
                .append("        }\n")
                .append("        function loadDetailFile(filePath, blockId) {\n")
                .append("            fetch(filePath)\n")
                .append("                .then(response => {\n")
                .append("                    if (!response.ok) throw new Error('文件加载失败: ' + response.statusText);\n")
                .append("                    return response.text();\n")
                .append("                })\n")
                .append("                .then(data => {\n")
                .append("                    var config = []; // 可选配置项\n")
                .append("                    new Diff2HtmlUI(document.getElementById(blockId), data, config).draw();\n")
                .append("                })\n")
                .append("                .catch(error => {\n")
                .append("                    console.error('读取文件时出错:', error);\n")
                .append("                    document.getElementById(blockId).textContent = '无法加载文件: ' + error.message;\n")
                .append("                });\n")
                .append("        }\n")
                .append("        function toggleAndLoadFiles(reponame, compareType, sha256, rowIndex) {\n")
                .append("            const detailsRow = document.getElementById('detailsRow' + rowIndex);\n")
                .append("            if (detailsRow.classList.contains('hidden')) {\n")
                .append("                loadFiles(reponame, compareType, sha256, rowIndex);\n")
                .append("            }\n")
                .append("            detailsRow.classList.toggle('hidden');\n")
                .append("        }\n")
                .append("        function showMoreLog(rowIndex) {\n")
                .append("            document.getElementById('logContentFirstLine' + rowIndex).classList.add('hidden');\n")
                .append("            document.getElementById('logShowMoreBtn' + rowIndex).classList.add('hidden');\n")
                .append("            document.getElementById('logContentFull' + rowIndex).classList.remove('hidden');\n")
                .append("        }\n")
                .append("        function toggleLogView(rowIndex) {\n")
                .append("            const firstLine = document.getElementById('logContentFirstLine' + rowIndex);\n")
                .append("            const fullContent = document.getElementById('logContentFull' + rowIndex);\n")
                .append("            const showMoreBtn = document.getElementById('logShowMoreBtn' + rowIndex);\n")
                .append("            \n")
                .append("            if (firstLine.classList.contains('hidden')) {\n")
                .append("            // 当前显示的是完整内容，切换为显示第一行内容\n")
                .append("            firstLine.classList.remove('hidden');\n")
                .append("            fullContent.classList.add('hidden');\n")
                .append("            showMoreBtn.textContent = '展示更多';\n")
                .append("            } else {\n")
                .append("           // 当前显示的是第一行内容，切换为显示完整内容\n")
                .append("           firstLine.classList.add('hidden');\n")
                .append("           fullContent.classList.remove('hidden');\n")
                .append("           showMoreBtn.textContent = '仅展示第一行';\n")
                .append("       }\n")
                .append("    }")
                .append("    </script>\n")
                .append("</body>\n")
                .append("</html>\n");

        return html.toString();
    }

    /**
     * 生成 index.html 文件
     *
     * @param resourceDir    资源根目录
     * @param htmlFileNames  HTML 文件名列表
     */
    public void generateIndexHtml(String resourceDir, List<String> htmlFileNames) throws IOException {
        StringBuilder html = new StringBuilder();
        html.append("<!DOCTYPE html>\n")
                .append("<html>\n")
                .append("<head>\n")
                .append("    <title>文件列表</title>\n")
                .append("    <meta charset=\"utf-8\">\n")
                .append("    <style>\n")
                .append("        body { font-family: Arial, sans-serif; margin: 20px; }\n")
                .append("        table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }\n")
                .append("        table, th, td { border: 1px solid #ccc; }\n")
                .append("        th, td { padding: 10px; text-align: left; }\n")
                .append("        th { background-color: #f4f4f4; }\n")
                .append("    </style>\n")
                .append("</head>\n")
                .append("<body>\n")
                .append("    <h1>文件列表</h1>\n")
                .append("    <table>\n")
                .append("        <thead>\n")
                .append("            <tr>\n")
                .append("                <th>文件名</th>\n")
                .append("            </tr>\n")
                .append("        </thead>\n")
                .append("        <tbody>\n");

        for (String htmlFileName : htmlFileNames) {
            html.append("            <tr>\n")
                    .append("                <td><a href=\"").append(htmlFileName).append("\">").append(htmlFileName).append("</a></td>\n")
                    .append("            </tr>\n");
        }

        html.append("        </tbody>\n")
                .append("    </table>\n")
                .append("</body>\n")
                .append("</html>\n");

        // 写入 index.html 文件
        Path indexPath = Paths.get(resourceDir, "index.html");
        Files.write(indexPath, html.toString().getBytes());
        System.out.println("生成 index.html 文件: " + indexPath);
    }

    /**
     * 处理 HTTP 请求，返回静态文件
     */
    static class FileHandler implements HttpHandler {
        private final String resourceDir;

        public FileHandler(String resourceDir) {
            this.resourceDir = resourceDir;
        }

        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String requestPath = exchange.getRequestURI().getPath();
            Path filePath = Paths.get(resourceDir, requestPath);

            if (Files.exists(filePath) && !Files.isDirectory(filePath)) {
                byte[] fileBytes = Files.readAllBytes(filePath);
                exchange.sendResponseHeaders(200, fileBytes.length);
                try (OutputStream os = exchange.getResponseBody()) {
                    os.write(fileBytes);
                }
            } else {
                String response = "文件未找到: " + requestPath;
                exchange.sendResponseHeaders(404, response.length());
                try (OutputStream os = exchange.getResponseBody()) {
                    os.write(response.getBytes());
                }
            }
        }
    }
}